<html>
<head><meta charset="utf-8"><title>implicit Sized bounds · t-compiler/rust-analyzer · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/index.html">t-compiler/rust-analyzer</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html">implicit Sized bounds</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="241936955"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/241936955" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dawer <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#241936955">(Jun 08 2021 at 15:21)</a>:</h4>
<p>I've been working on adding implicit Sized bounds <a href="https://github.com/rust-analyzer/rust-analyzer/issues/8984">https://github.com/rust-analyzer/rust-analyzer/issues/8984</a> <br>
Sorry for the delay and sorry for the long writing.<br>
<strong>TLDR</strong> I got a failing test of unsize coercion I cannot grasp how to fix it by myself. </p>
<p>The failing test is <code>tests::coercion::coerce_unsize_trait_object_simple</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[lang = </span><span class="s">"sized"</span><span class="cp">]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nb">Sized</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="cp">#[lang = </span><span class="s">"unsize"</span><span class="cp">]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">Unsize</span><span class="o">&lt;</span><span class="n">T</span>: <span class="o">?</span><span class="nb">Sized</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="cp">#[lang = </span><span class="s">"coerce_unsized"</span><span class="cp">]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">CoerceUnsized</span><span class="o">&lt;</span><span class="n">T</span>: <span class="o">?</span><span class="nb">Sized</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span>: <span class="o">?</span><span class="nb">Sized</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Unsize</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">U</span>: <span class="o">?</span><span class="nb">Sized</span><span class="o">&gt;</span><span class="w"> </span><span class="n">CoerceUnsized</span><span class="o">&lt;&amp;</span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="o">&amp;</span><span class="n">T</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">trait</span><span class="w"> </span><span class="n">Foo</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">Bar</span><span class="o">&lt;</span><span class="n">U</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span>: <span class="nc">Foo</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">Baz</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span>: <span class="nc">Bar</span><span class="o">&lt;</span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">struct</span> <span class="nc">S</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="p">;</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Foo</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="kt">usize</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">S</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Bar</span><span class="o">&lt;</span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">S</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Baz</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">S</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">X</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">test</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">obj</span>: <span class="kp">&amp;</span><span class="nc">dyn</span><span class="w"> </span><span class="n">Baz</span><span class="o">&lt;</span><span class="kt">i8</span><span class="p">,</span><span class="w"> </span><span class="kt">i16</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">S</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">obj</span>: <span class="kp">&amp;</span><span class="nc">dyn</span><span class="w"> </span><span class="n">Bar</span><span class="o">&lt;</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="kt">i8</span><span class="p">,</span><span class="w"> </span><span class="kt">i16</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">S</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">obj</span>: <span class="kp">&amp;</span><span class="nc">dyn</span><span class="w"> </span><span class="n">Foo</span><span class="o">&lt;</span><span class="kt">i8</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">S</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<div class="codehilite"><pre><span></span><code>Expect:
----
457..572 &#39;{     ... &amp;S; }&#39;: ()
467..470 &#39;obj&#39;: &amp;dyn Baz&lt;i8, i16&gt;
492..494 &#39;&amp;S&#39;: &amp;S&lt;i8, i16&gt;
493..494 &#39;S&#39;: S&lt;i8, i16&gt;
504..507 &#39;obj&#39;: &amp;dyn Bar&lt;usize, i8, i16&gt;
532..534 &#39;&amp;S&#39;: &amp;S&lt;i8, i16&gt;
533..534 &#39;S&#39;: S&lt;i8, i16&gt;
544..547 &#39;obj&#39;: &amp;dyn Foo&lt;i8, usize&gt;
567..569 &#39;&amp;S&#39;: &amp;S&lt;i8, {unknown}&gt;
568..569 &#39;S&#39;: S&lt;i8, {unknown}&gt;

----

Actual:
----
457..572 &#39;{     ... &amp;S; }&#39;: ()
467..470 &#39;obj&#39;: &amp;dyn Baz&lt;i8, i16&gt;
492..494 &#39;&amp;S&#39;: &amp;S&lt;i8, i16&gt;
493..494 &#39;S&#39;: S&lt;i8, i16&gt;
504..507 &#39;obj&#39;: &amp;dyn Bar&lt;usize, i8, i16&gt;
532..534 &#39;&amp;S&#39;: &amp;S&lt;i8, i16&gt;
533..534 &#39;S&#39;: S&lt;i8, i16&gt;
544..547 &#39;obj&#39;: &amp;dyn Foo&lt;i8, {unknown}&gt;
567..569 &#39;&amp;S&#39;: &amp;S&lt;{unknown}, {unknown}&gt;
568..569 &#39;S&#39;: S&lt;{unknown}, {unknown}&gt;
567..569: expected &amp;dyn Foo&lt;i8, {unknown}&gt;, got &amp;S&lt;{unknown}, {unknown}&gt;
</code></pre></div>
<p>The last coercion fails. It is expected to success with 1 inference var left unbound but, with implicit Sized bounds, Chalk returns <code>ambiguous</code>. The ambiguity here is treated as no-success <a href="https://github.com/rust-analyzer/rust-analyzer/blob/16e142cd395f264ba5c6c3814ece92431415c089/crates/hir_ty/src/infer/coerce.rs#L409-L422">hir_ty/src/infer/coerce.rs#L409-L422</a>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="w">        </span><span class="k">match</span><span class="w"> </span><span class="n">solution</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">Solution</span>::<span class="n">Unique</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">canonicalized</span><span class="p">.</span><span class="n">apply_solution</span><span class="p">(</span><span class="w"></span>
<span class="w">                    </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">table</span><span class="p">,</span><span class="w"></span>
<span class="w">                    </span><span class="n">Canonical</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                        </span><span class="n">binders</span>: <span class="nc">v</span><span class="p">.</span><span class="n">binders</span><span class="p">,</span><span class="w"></span>
<span class="w">                        </span><span class="c1">// FIXME handle constraints</span>
<span class="w">                        </span><span class="n">value</span>: <span class="nc">v</span><span class="p">.</span><span class="n">value</span><span class="p">.</span><span class="n">subst</span><span class="p">,</span><span class="w"></span>
<span class="w">                    </span><span class="p">},</span><span class="w"></span>
<span class="w">                </span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="c1">// FIXME: should we accept ambiguous results here?</span>
<span class="w">            </span><span class="n">_</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">TypeError</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
</code></pre></div>
<p>I can use <code>Solution::Ambiguous(definitely_inferred)</code> to update U in <code>dyn Foo&lt;i8, U=usize&gt;</code> but should we treat the ambiguity as successful coercion? </p>
<p>I recorded logs <code>CHALK_DEBUG=info CHALK_PRINT=1 cargo test --package hir_ty --lib -- --nocapture tests::coercion::coerce_unsize_trait_object_simple --exact &amp;&gt;</code> <a href="/user_uploads/4715/KW53ca6Wj5vzyMx_BTv-kRjK/coerce_unsize_trait_object_simple.log">log</a> . So for the last coercion it says:</p>
<div class="codehilite"><pre><span></span><code>┐solve_goal goal=UCanonical { canonical: Canonical { value: InEnvironment { environment: Env([]), goal: Implemented((&amp;&#39;static S&lt;[?0 := ^0.0, ?1 := ^0.1]&gt;): CoerceUnsized&lt;(&amp;&#39;static dyn for&lt;type&gt; [for&lt;&gt; Implemented(^1.0: Foo&lt;Int(I8), ^2.2&gt;)] + &#39;static)&gt;) }, binders: [U0 with kind type, U0 with kind type, U0 with kind type] }, universes: 1 }
&lt;snip&gt;
├─89ms INFO solve_goal: solution = Ok(Ambig(Definite(Canonical { value: [?0 := Int(I8), ?1 := ^0.0, ?2 := Uint(Usize)], binders: [U0 with kind type] }))) prio High
┘
</code></pre></div>
<p>Then I tried to reproduce the query in Chalk REPL (still not sure which one represents the query r-a does; Chalk program dump is in the log)</p>
<div class="codehilite"><pre><span></span><code>?- exists&lt;T,U,X&gt; {
    &amp;&#39;static S&lt;T,X&gt;: CoerceUnsized&lt;&amp;&#39;static (dyn Foo&lt;i8, U&gt; + &#39;static)&gt;
}
Ambiguous; no inference guidance

?- forall&lt;X&gt; {
    exists&lt;T,U&gt; {
        &amp;&#39;static S&lt;T,X&gt;: CoerceUnsized&lt;&amp;&#39;static (dyn Foo&lt;i8, U&gt; + &#39;static)&gt;
    }
}
No possible solution.

?- forall&lt;X&gt; {
    exists&lt;T,U&gt; {
        if (X:Sized) {
           &amp;&#39;static S&lt;T,X&gt;: CoerceUnsized&lt;&amp;&#39;static (dyn Foo&lt;i8, U&gt; + &#39;static)&gt;
        }
    }
}
Unique; substitution [?0 := Int(I8), ?1 := Uint(Usize)], lifetime constraints [InEnvironment { environment: Env([]), goal: S&lt;Int(I8), !1_0&gt;: &#39;static }]

?- forall&lt;X&gt; {
    exists&lt;T,U&gt; {
        if (FromEnv(S&lt;T,X&gt;)) {
           &amp;&#39;static S&lt;T,X&gt;: CoerceUnsized&lt;&amp;&#39;static (dyn Foo&lt;i8, U&gt; + &#39;static)&gt;
        }
    }
}
Unique; substitution [?0 := Int(I8), ?1 := Uint(Usize)], lifetime constraints [InEnvironment { environment: Env([]), goal: S&lt;Int(I8), !1_0&gt;: &#39;static }]
</code></pre></div>
<p>So chalk finds a solution with <code>if(X:Sized) {..}</code> or <code>if(FromEnv(S&lt;T,X&gt;))</code> implications. <del>But isn't it might infer this somehow?</del> Does this mean we could provide to chalk some <code>FromEnv(from_ty) &amp;&amp; FromEnv(to_ty)</code> assumptions about well-formedness?</p>



<a name="241937525"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/241937525" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dawer <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#241937525">(Jun 08 2021 at 15:25)</a>:</h4>
<p><code>FromEnv(&amp;'static S&lt;T,X&gt;)</code> did not work. Have to look into inner types then..  <span aria-label="thinking" class="emoji emoji-1f914" role="img" title="thinking">:thinking:</span></p>
<div class="codehilite"><pre><span></span><code>?- forall&lt;X&gt; {
    exists&lt;T,U&gt; {
        if (FromEnv(&amp;&#39;static S&lt;T,X&gt;)) {
           &amp;&#39;static S&lt;T,X&gt;: CoerceUnsized&lt;&amp;&#39;static (dyn Foo&lt;i8, U&gt; + &#39;static)&gt;
        }
    }
}
No possible solution.
</code></pre></div>



<a name="241950554"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/241950554" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#241950554">(Jun 08 2021 at 16:50)</a>:</h4>
<div class="codehilite"><pre><span></span><code>exists&lt;T,U,X&gt; {
    &amp;&#39;static S&lt;T,X&gt;: CoerceUnsized&lt;&amp;&#39;static (dyn Foo&lt;i8, U&gt; + &#39;static)&gt;
}
</code></pre></div>
<p>is the correct query unless I'm missing something</p>



<a name="241950635"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/241950635" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#241950635">(Jun 08 2021 at 16:51)</a>:</h4>
<p>I'm not sure this is supposed to work, since the expected result already has an uninferred type anyway</p>



<a name="241950787"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/241950787" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#241950787">(Jun 08 2021 at 16:52)</a>:</h4>
<p>rustc actually doesn't do normal trait solving in that place, so it's really hard to tell whether we should be accepting ambiguous results or not or whether neither will do what we need</p>



<a name="241950903"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/241950903" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#241950903">(Jun 08 2021 at 16:53)</a>:</h4>
<p>we could try seeing what happens if we allow ambiguous results there; we would need to return the obligation so it can be fully checked later</p>



<a name="245602041"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/245602041" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Florian Diebold <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#245602041">(Jul 11 2021 at 11:20)</a>:</h4>
<p><span class="user-mention" data-user-id="319948">@Dawer</span> did you make progress on this? you could put up a draft PR if it's not quite working yet</p>



<a name="247571664"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/247571664" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dawer <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#247571664">(Jul 29 2021 at 11:38)</a>:</h4>
<p>Sorry for being missing for a long time!<br>
Most of things are done. The last issue I recall was that rebasing onto master with minicore feature revealed <del>another place where it needs to accept ambiguous results</del> some broken tests. I'll refresh my context on this and continue soon.</p>



<a name="247571692"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/implicit%20Sized%20bounds/near/247571692" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dawer <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/implicit.20Sized.20bounds.html#247571692">(Jul 29 2021 at 11:38)</a>:</h4>
<p>(I should have notify that I will be unavailable and make a draft PR before a go for a long time)</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>